package tme.kvstore;
import oracle.kv.*;

/**
 * TME avec KVStore : Init
 */
public class EX_1 {

	private final KVStore store;

	public static void main(String args[]) {
		try {
			EX_1 a = new EX_1(args);
			// a.A1();
			a.A2();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private EX_1(String[] argv) {

		String storeName = "kvstore";
		String hostName = "localhost";
		String hostPort = "5000";

		final int nArgs = argv.length;
		int argc = 0;

		while (argc < nArgs) {
			final String thisArg = argv[argc++];

			if (thisArg.equals("-store")) {
				if (argc < nArgs) {
					storeName = argv[argc++];
				} else {
					usage("-store requires an argument");
				}
			} else if (thisArg.equals("-host")) {
				if (argc < nArgs) {
					hostName = argv[argc++];
				} else {
					usage("-host requires an argument");
				}
			} else if (thisArg.equals("-port")) {
				if (argc < nArgs) {
					hostPort = argv[argc++];
				} else {
					usage("-port requires an argument");
				}
			} else {
				usage("Unknown argument: " + thisArg);
			}
		}

		store = KVStoreFactory.getStore(new KVStoreConfig(storeName, hostName
				+ ":" + hostPort));
	}

	private void usage(String message) {
		System.out.println("\n" + message + "\n");
		System.out.println("usage: " + getClass().getName());
		System.out.println("\t-store <instance name> (default: kvstore) "
				+ "-host <host name> (default: localhost) "
				+ "-port <port number> (default: 5000)");
		System.exit(1);
	}

	public void A1() {
		for (int i = 0; i < 10000; i++) {
			// Lit la quantite recente de P1
			ValueVersion valueVersion = store.get(Key.createKey("P1"));
			String quantite = new String(valueVersion.getValue().getValue());
			// la imprime
			System.out.println("P1" + " " + quantite);
			// Ajoute 1
			Integer amount = Integer.parseInt(quantite);
			amount++;
			String newValue = String.valueOf(amount);
			// Mise à jour
			store.put(Key.createKey("P1"),
					Value.createValue(newValue.getBytes()));
		}
	}

	/**
	 * utiliser l'ecriture conditionnelle pour contrôler l'execution simultanee
	 * de plusieurs programmes.
	 * 
	 * voir la methode putIfVersion. La valeur de retour est nulle lorsque
	 * l'ecriture est refusee.
	 * */
	public void A2() {
		for (int i = 0; i < 10000; i++) {
			// Lit la quantite recente de P1
			ValueVersion valueVersion = store.get(Key.createKey("P1"));
			// Obtien la version recente
			Version marchVersion = valueVersion.getVersion();
			String quantite = new String(valueVersion.getValue().getValue());
			// la imprime
			System.out.println("P1" + " " + quantite);
			// Ajoute 1
			Integer amount = Integer.parseInt(quantite);
			amount++;
			String newValue = String.valueOf(amount);
			// Mise a jour sous l'ecriture conditionnelle
			Version nouvelleVersion = store.putIfVersion(Key.createKey("P1"),
					Value.createValue(newValue.getBytes()), marchVersion);
			if (nouvelleVersion == null) {
				// System.out.println("Oops");
				i--;
			}
		}
	}
}